package base;

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;

public class Grid extends JPanel {
	// Đánh Square đang sử dụng
	protected Square selectedSquare;

	/********************************/

	protected ArrayList squares; // Danh sách các Square

	// Đánh đấu từ đang sử dụng
	protected Word selectedWord;
	protected Word keyWord;

	/***************************************/

	// Đánh dấu từ trong quá trình tạo
	private Word previousWord;

	// Đánh dấu các Square trong quá trình tạo
	private Square startSquare;
	private Square endSquare;
	private Square previousSquare;
	private Square nextSquare;

	protected Crossword crossword; // Ô chữ
	private String inputText; // Xâu nhập từ
	private int option = -1; // Lựa chọn nhập từ
	private int positionDuplicate = -1;
	private boolean activeKey = false; // Đánh dấu việc tạo keyWord
	private boolean setKeyWord = false; // Kiểm tra keyWord có hay chưa
	private boolean doMoveStart = false; // Đánh dấu sự kiện kéo thả
	private boolean doSelectStart = false; // Đánh dấu sự kiện tạo từ bằng đồ
											// họa
	private boolean doSelectEnd = false;

	/********************************* Khởi tạo *******************************/

	public Grid() {

	}

	// Tạo Grid từ một crossword có sẵn
	public Grid(Crossword cw) {
		this.crossword = cw;
		setFocusable(true); // allow the jpanel to receive focus
		squares = new ArrayList();
		selectedWord = null;
		setLayout(new GridLayout(cw.getHeight(), cw.getWidth()));
		addKeyListener(new KListener());
		this.setBackground(Color.black);
	}

	// Format một Square
	private void formatSquare(Square s) {
		s.setBackground(Color.WHITE);
		s.setResetColour(Color.WHITE);
		s.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
		s.setIsBlank(false);
	}

	// Bôi đen tất cả Square
	private void blankSquares() {
		for (int i = 0; i < squares.size(); i++) {
			Square s = (Square) squares.get(i);
			s.setBackground(Color.BLACK);
			s.blank();
		}
	}

	// Giải phóng các Square
	private void dissociateSquares() {
		for (int i = 0; i < squares.size(); i++) {
			Square s = (Square) squares.get(i);
			if (s.getIsBlank()) {
				s.setNoWord();
			}
		}
	}

	// Tạo ô chữ từ ô chữ có sẵn
	public void setCrossword(Crossword cw) {
		this.crossword = cw;

		// Gắn các Square vào các từ trong ô chữ
		ArrayList words = cw.getWords();
		keyWord = cw.getKey();
		if (keyWord != null)
			setKeyWord = true;
		for (int k = 0; k < words.size(); k++) {
			Word word = (Word) words.get(k);
			if (word.getWordDirection() == Word.ACROSS) {
				for (int i = word.getX(), letterIndex = 0; i < (word.getX() + word
						.getLength()); i++, letterIndex++) {
					Square s = findSquare(word.getY(), i);
					s.setWord(word);
					s.setLetterIndexAcross(letterIndex);
				}
			} else if (word.getWordDirection() == Word.DOWN) {
				for (int i = word.getY(), letterIndex = 0; i < (word.getY() + word
						.getLength()); i++, letterIndex++) {
					Square s = findSquare(i, word.getX());
					s.setWord(word);
					s.setLetterIndexDown(letterIndex);
				}
			} else if (word.getWordDirection() == Word.BIAS1) {
				for (int i = word.getY(), letterIndex = 0; i < (word.getY() + word
						.getLength()); i++, letterIndex++) {
					Square s = findSquare(i, word.getX() + letterIndex);
					s.setWord(word);
					s.setLetterIndexBias1(letterIndex);
				}
			} else if (word.getWordDirection() == Word.BIAS2) {
				for (int i = word.getX(), letterIndex = 0; i < (word.getX() + word
						.getLength()); i++, letterIndex++) {
					Square s = findSquare(word.getY() - letterIndex, i);
					s.setWord(word);
					s.setLetterIndexBias2(letterIndex);
				}
			}
		}
	}

	// Lấy ô chữ
	public Crossword getCrossword() {
		return crossword;
	}

	// Xây dựng Grid
	public void Build() {
		for (int i = 0; i < crossword.getHeight(); i++) {
			for (int j = 0; j < crossword.getWidth(); j++) {
				Square s = new Square(i, j, Color.BLACK);
				s.setResetColour(Color.BLACK);
				s.addMouseListener(new SquareListener());
				s.addMouseMotionListener(new SquareMotionListener());
				s.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
				squares.add(s);
				s.setFontSize(250 / crossword.getWidth());
				add(s);
			}
		}

	}

	/******************************** Thêm từ ********************************/

	// Tạo từ trong khi kéo thả
	public Word createWord() {
		Word word = null;
		int rowStart = startSquare.getXPos();
		int colStart = startSquare.getYPos();
		int rowEnd = endSquare.getXPos();
		int colEnd = endSquare.getYPos();
		int direction = 0;
		int length = 0;

		// xác định direction của từ
		if (rowStart == rowEnd) {
			direction = Word.ACROSS;
			length = colEnd - colStart + 1;
		} else if (colStart == colEnd) {
			direction = Word.DOWN;
			length = rowEnd - rowStart + 1;
		} else if (colEnd - colStart == rowEnd - rowStart) {
			direction = Word.BIAS1;
			length = colEnd - colStart + 1;
		} else if (rowEnd - rowStart == colStart - colEnd) {
			direction = Word.BIAS2;
			length = colEnd - colStart + 1;
		}

		// thiết lập từ theo từng Square
		if (direction == Word.ACROSS) {
			word = new Word(colStart, rowStart, direction, length);
			crossword.addWord(word);
			for (int i = colStart, letterIndex = 0; i <= colEnd; i++, letterIndex++) {
				Square s = findSquare(rowStart, i);
				ArrayList letter = previousWord.getLetters();
				formatSquare(s);
				if (s.getWord(Word.ACROSS) == null) {
					s.setWord(word);
					s.setLetterIndexAcross(letterIndex);
					word.addLetter((String) letter.get(letterIndex),
							letterIndex);
				}

			}

		} else if (direction == Word.DOWN) {
			word = new Word(colStart, rowStart, direction, length);
			crossword.addWord(word);
			for (int i = rowStart, letterIndex = 0; i <= rowEnd; i++, letterIndex++) {
				Square s = findSquare(i, colStart);
				ArrayList letter = previousWord.getLetters();
				formatSquare(s);
				if (s.getWord(Word.DOWN) == null) {
					s.setWord(word);
					s.setLetterIndexDown(letterIndex);
					word.addLetter((String) letter.get(letterIndex),
							letterIndex);
				}
			}
		} else if (direction == Word.BIAS1) {
			word = new Word(colStart, rowStart, direction, length);
			crossword.addWord(word);
			for (int i = colStart, letterIndex = 0; i <= colEnd; i++, letterIndex++) {
				Square s = findSquare(rowStart + letterIndex, i);
				ArrayList letter = previousWord.getLetters();
				formatSquare(s);
				if (s.getWord(Word.BIAS1) == null) {
					s.setWord(word);
					s.setLetterIndexBias1(letterIndex);
					word.addLetter((String) letter.get(letterIndex),
							letterIndex);
				}
			}
		} else if (direction == Word.BIAS2) {
			word = new Word(colStart, rowStart, direction, length);
			crossword.addWord(word);
			for (int i = colStart, letterIndex = 0; i <= colEnd; i++, letterIndex++) {
				Square s = findSquare(rowStart - letterIndex, i);
				ArrayList letter = previousWord.getLetters();
				formatSquare(s);
				if (s.getWord(Word.BIAS2) == null) {
					s.setWord(word);
					s.setLetterIndexBias2(letterIndex);
					word.addLetter((String) letter.get(letterIndex),
							letterIndex);
				}
			}
		}
		return word;
	}

	// Đưa một từ cho sẵn vào ô chữ
	public Word createPreviousWord(Word a) {
		int direction = a.getWordDirection();
		int rowStart = a.getY();
		int colStart = a.getX();
		int length = a.getLength();

		// thiết lập từ theo từng Square
		if (direction == Word.ACROSS) {

			crossword.addWord(a);
			for (int i = colStart, letterIndex = 0; i <= colStart + length - 1; i++, letterIndex++) {
				Square s = findSquare(rowStart, i);
				formatSquare(s);
				s.setWord(a);
				s.setLetterIndexAcross(letterIndex);
			}
		} else if (direction == Word.DOWN) {
			crossword.addWord(a);
			for (int i = rowStart, letterIndex = 0; i <= rowStart + length - 1; i++, letterIndex++) {
				Square s = findSquare(i, colStart);
				formatSquare(s);
				s.setWord(a);
				s.setLetterIndexDown(letterIndex);
			}
		} else if (direction == Word.BIAS1) {
			crossword.addWord(a);
			for (int i = colStart, letterIndex = 0; i <= colStart + length - 1; i++, letterIndex++) {
				Square s = findSquare(rowStart + letterIndex, i);
				formatSquare(s);
				s.setWord(a);
				s.setLetterIndexBias1(letterIndex);
			}
		} else if (direction == Word.BIAS2) {
			crossword.addWord(a);
			for (int i = colStart, letterIndex = 0; i <= colStart + length - 1; i++, letterIndex++) {
				Square s = findSquare(rowStart - letterIndex, i);
				formatSquare(s);
				s.setWord(a);
				s.setLetterIndexBias2(letterIndex);
			}

		}
		return a;
	}

	// Thêm từ theo kiểu gõ
	public void addWordType(int temp) {
		inputText = JOptionPane.showInputDialog(null, "Nhập từ :");
		if (inputText != null) {
			if (inputText.contains(" ")) {
				JOptionPane.showMessageDialog(null,
						"Bạn nhập từ có dấu cách !", "Type Error",
						JOptionPane.ERROR_MESSAGE);
				addWordType(temp);
			} else if (checkWordDuplicate(inputText)) {
				JOptionPane.showMessageDialog(null, inputText.toUpperCase()
						+ " trùng với từ đã có", "Word Duplicate",
						JOptionPane.ERROR_MESSAGE);
				addWordType(temp);
			}

			else
				option = temp;
		}
	}

	// thêm từ bằng kiểu đồ họa
	public boolean createWordDraw() {
		int rowStart = startSquare.getXPos();
		int colStart = startSquare.getYPos();
		int rowEnd = endSquare.getXPos();
		int colEnd = endSquare.getYPos();
		int direction = 0;
		int length = 0;

		// xác định hướng của ô chữ
		if (rowStart == rowEnd) {
			direction = Word.ACROSS;
			length = colEnd - colStart + 1;
		} else if (colStart == colEnd) {
			direction = Word.DOWN;
			length = rowEnd - rowStart + 1;
		} else if (colEnd - colStart == rowEnd - rowStart) {
			direction = Word.BIAS1;
			length = colEnd - colStart + 1;
		} else if (rowEnd - rowStart == colStart - colEnd) {
			direction = Word.BIAS2;
			length = colEnd - colStart + 1;
		}

		// thiết lập từ theo từng Square
		if (direction == Word.ACROSS) {

			int temp = 1;
			for (int i = colStart, letterIndex = 0; i <= colEnd; i++, letterIndex++) {
				Square s = findSquare(rowStart, i);
				if (s.getWord(Word.ACROSS) != null) {
					temp = 0;
					break;
				}
			}
			if (temp == 0) {
				JOptionPane.showMessageDialog(null, "Ô chữ nhập không hợp lệ");
				return false;
			} else {
				Word word = new Word(colStart, rowStart, direction, length);
				crossword.addWord(word);
				for (int i = colStart, letterIndex = 0; i <= colEnd; i++, letterIndex++) {
					Square s = findSquare(rowStart, i);
					formatSquare(s);
					s.setWord(word);
					s.setLetterIndexAcross(letterIndex);
					if (!s.getLetter().equals("")) {
						word.addLetter(s.getLetter(), letterIndex);
					}
				}
				if (activeKey == true) // kiểm tra xem có phải chức năng thêm từ
										// khóa không
				{
					keyWord = word;
					setKeyWord = true;
					activeKey = false;
				}

			}
		} else if (direction == Word.DOWN) {

			int temp = 1;
			for (int i = rowStart, letterIndex = 0; i <= rowEnd; i++, letterIndex++) {
				Square s = findSquare(i, colStart);
				if (s.getWord(Word.DOWN) != null) {
					temp = 0;
					break;
				}
			}
			if (temp == 0) {
				JOptionPane.showMessageDialog(null, "Ô chữ nhập không hợp lệ");
				return false;
			} else {
				Word word = new Word(colStart, rowStart, direction, length);
				crossword.addWord(word);
				for (int i = rowStart, letterIndex = 0; i <= rowEnd; i++, letterIndex++) {
					Square s = findSquare(i, colStart);
					formatSquare(s);
					s.setWord(word);
					s.setLetterIndexDown(letterIndex);
					if (!s.getLetter().equals("")) {
						word.addLetter(s.getLetter(), letterIndex);
					}
				}
				if (activeKey == true) // kiểm tra xem có phải chức năng thêm từ
										// khóa không
				{
					keyWord = word;
					setKeyWord = true;
					activeKey = false;
				}

			}
		} else if (direction == Word.BIAS1) {

			int temp = 1;
			for (int i = colStart, letterIndex = 0; i <= colEnd; i++, letterIndex++) {
				Square s = findSquare(rowStart + letterIndex, i);
				if (s.getWord(Word.BIAS1) != null) {
					temp = 0;
					break;
				}
			}
			if (temp == 0) {
				JOptionPane.showMessageDialog(null, "Ô chữ nhập không hợp lệ");
				return false;
			} else {
				Word word = new Word(colStart, rowStart, direction, length);
				crossword.addWord(word);
				for (int i = colStart, letterIndex = 0; i <= colEnd; i++, letterIndex++) {
					Square s = findSquare(rowStart + letterIndex, i);
					formatSquare(s);
					s.setWord(word);
					s.setLetterIndexBias1(letterIndex);
					if (!s.getLetter().equals("")) {
						word.addLetter(s.getLetter(), letterIndex);
					}
				}
				if (activeKey == true) // kiểm tra xem có phải chức năng thêm từ
										// khóa không
				{
					keyWord = word;
					setKeyWord = true;
					activeKey = false;
				}

			}
		} else if (direction == Word.BIAS2) {

			int temp = 1;
			for (int i = colStart, letterIndex = 0; i <= colEnd; i++, letterIndex++) {
				Square s = findSquare(rowStart - letterIndex, i);
				if (s.getWord(Word.BIAS2) != null) {
					temp = 0;
					break;
				}
			}
			if (temp == 0) {
				JOptionPane.showMessageDialog(null, "Ô chữ nhập không hợp lệ");
				return false;
			} else {
				Word word = new Word(colStart, rowStart, direction, length);
				crossword.addWord(word);
				for (int i = colStart, letterIndex = 0; i <= colEnd; i++, letterIndex++) {
					Square s = findSquare(rowStart - letterIndex, i);
					formatSquare(s);
					s.setWord(word);
					s.setLetterIndexBias2(letterIndex);
					if (!s.getLetter().equals("")) {
						word.addLetter(s.getLetter(), letterIndex);
					}
				}
				if (activeKey == true) // kiểm tra xem có phải chức năng thêm
										// chìa khóa không
				{
					keyWord = word;
					setKeyWord = true;
					activeKey = false;
				}

			}
		}
		return true;
	}

	// Tạo từ theo kiểu gõ
	public boolean createWordType() {
		int rowStart = startSquare.getXPos();
		int colStart = startSquare.getYPos();
		int rowEnd = endSquare.getXPos();
		int colEnd = endSquare.getYPos();
		int direction = 0;
		int length = 0;

		// Xác định hướng của từ bằng tham số option
		if (option == 0)
			direction = Word.ACROSS;
		if (option == 1)
			direction = Word.DOWN;
		if (option == 2)
			direction = Word.BIAS1;
		if (option == 3)
			direction = Word.BIAS2;
		if (rowStart == rowEnd) {

			length = colEnd - colStart + 1;
		} else if (colStart == colEnd) {

			length = rowEnd - rowStart + 1;
		} else if (colEnd - colStart == rowEnd - rowStart) {

			length = colEnd - colStart + 1;
		} else if (rowEnd - rowStart == colStart - colEnd) {

			length = colEnd - colStart + 1;
		}

		// thiết lập từ theo từng Square
		if (direction == Word.ACROSS) {

			int temp = 1;
			for (int i = colStart, letterIndex = 0; i <= colEnd; i++, letterIndex++) {
				Square s = findSquare(rowStart, i);
				if (s.getWord(Word.ACROSS) != null) {
					temp = 0;
					break;
				}
			}
			if (temp == 0) {
				JOptionPane.showMessageDialog(null, "Ô chữ nhập không hợp lệ");
				return false;
			} else {
				Word word = new Word(colStart, rowStart, direction, length);
				crossword.addWord(word);
				for (int i = colStart, letterIndex = 0; i <= colEnd; i++, letterIndex++) {
					Square s = findSquare(rowStart, i);
					formatSquare(s);
					s.setWord(word);
					s.setLetterIndexAcross(letterIndex);
					String m = (String) s.getLetter();
					word.addLetter(String
							.valueOf(inputText.charAt(letterIndex)),
							letterIndex);
				}
				selectedWord = word;
                                if (activeKey == true) // kiểm tra xem có phải chức năng thêm từ
										// khóa không
				{
					keyWord = word;
					setKeyWord = true;
					activeKey = false;
				}

			}

		} else if (direction == Word.DOWN) {

			int temp = 1;

			for (int i = rowStart, letterIndex = 0; i <= rowEnd; i++, letterIndex++) {
				Square s = findSquare(i, colStart);
				if (s.getWord(Word.DOWN) != null) {
					temp = 0;
					break;
				}
			}
			if (temp == 0) {
				JOptionPane.showMessageDialog(null, "Ô chữ nhập không hợp lệ");
				return false;
			} else {
				Word word = new Word(colStart, rowStart, direction, length);
				crossword.addWord(word);
				for (int i = rowStart, letterIndex = 0; i <= rowEnd; i++, letterIndex++) {
					Square s = findSquare(i, colStart);
					formatSquare(s);
					s.setWord(word);
					s.setLetterIndexDown(letterIndex);
					word.addLetter(String
							.valueOf(inputText.charAt(letterIndex)),
							letterIndex);
				}
				selectedWord = word;
                                if (activeKey == true) // kiểm tra xem có phải chức năng thêm từ
										// khóa không
				{
					keyWord = word;
					setKeyWord = true;
					activeKey = false;
				}

			}
		} else if (direction == Word.BIAS1) {

			int temp = 1;
			for (int i = colStart, letterIndex = 0; i <= colEnd; i++, letterIndex++) {
				Square s = findSquare(rowStart + letterIndex, i);
				if (s.getWord(Word.BIAS1) != null) {
					temp = 0;
					break;
				}
			}
			if (temp == 0) {
				JOptionPane.showMessageDialog(null, "Ô chữ nhập không hợp lệ");
				return false;
			} else {
				Word word = new Word(colStart, rowStart, direction, length);
				crossword.addWord(word);
				for (int i = colStart, letterIndex = 0; i <= colEnd; i++, letterIndex++) {
					Square s = findSquare(rowStart + letterIndex, i);
					formatSquare(s);
					s.setWord(word);
					s.setLetterIndexBias1(letterIndex);
					word.addLetter(String
							.valueOf(inputText.charAt(letterIndex)),
							letterIndex);
				}
				selectedWord = word;

			}
		} else if (direction == Word.BIAS2) {

			int temp = 1;
			for (int i = colStart, letterIndex = 0; i <= colEnd; i++, letterIndex++) {
				Square s = findSquare(rowStart - letterIndex, i);
				if (s.getWord(Word.BIAS2) != null) {
					temp = 0;
					break;
				}
			}
			if (temp == 0) {
				JOptionPane.showMessageDialog(null, "Ô chữ nhập không hợp lệ");
				return false;
			} else {
				Word word = new Word(colStart, rowStart, direction, length);
				crossword.addWord(word);
				for (int i = colStart, letterIndex = 0; i <= colEnd; i++, letterIndex++) {
					Square s = findSquare(rowStart - letterIndex, i);
					formatSquare(s);
					s.setWord(word);
					s.setLetterIndexBias2(letterIndex);
					word.addLetter(String
							.valueOf(inputText.charAt(letterIndex)),
							letterIndex);
				}
				selectedWord = word;

			}
		}
		setLetter(selectedWord);
		return true;
	}

	// xóa từ đang lựa chọn
	public void deleteSelectedWord() {

		ArrayList al = crossword.getWords();
		if (selectedWord == keyWord) // kiểm tra nó có phải là keyword không
		{
			setKeyWord(false);
		}

		// xóa theo từng Square dựa theo hướng và tọa độ khởi tạo từ
		if (selectedWord.getWordDirection() == Word.ACROSS) {
			for (int i = 0; i < selectedWord.getLength(); i++) {
				Square s = findSquare(selectedWord.getY(), selectedWord.getX()
						+ i);
				if (s.getWord(Word.ACROSS) == selectedWord) {
					s.setWordNull(Word.ACROSS);
				}
			}
		} else if (selectedWord.getWordDirection() == Word.DOWN) {
			for (int i = 0; i < selectedWord.getLength(); i++) {
				Square s = findSquare(selectedWord.getY() + i, selectedWord
						.getX());
				if (s.getWord(Word.DOWN) == selectedWord) {
					s.setWordNull(Word.DOWN);
				}
			}
		}
		if (selectedWord.getWordDirection() == Word.BIAS1) {
			for (int i = 0; i < selectedWord.getLength(); i++) {
				Square s = findSquare(selectedWord.getY() + i, selectedWord
						.getX()
						+ i);
				if (s.getWord(Word.BIAS1) == selectedWord) {
					s.setWordNull(Word.BIAS1);
				}
			}
		}
		if (selectedWord.getWordDirection() == Word.BIAS2) {
			for (int i = 0; i < selectedWord.getLength(); i++) {
				Square s = findSquare(selectedWord.getY() - i, selectedWord
						.getX()
						+ i);
				if (s.getWord(Word.BIAS2) == selectedWord) {
					s.setWordNull(Word.BIAS2);
				}
			}
		}
		al.remove(selectedWord);
		// if(al.isEmpty()==true) acrossWord=false;
		repopulateWords();
	}

	/***************************** SET&GET *********************************/

	public void setSelectedWord(Word w) {
		selectedWord = w;
	}
       
        // Lấy từ đang được chọn
	public Word getSelectedWord() {
		return selectedWord;
	}
        public Square getSelectedSquare(){
            return selectedSquare;
        }
        
	// Lấy toàn bộ từ đi qua một Square
	public ArrayList getAllSelectedWords() {
		return selectedSquare.getAllWords();
	}

	

	// Lấy và tạo từ được dánh đấu
	public void setPreivousWord(Word a) {
		previousWord = a;
	}

	public Word getPreviousWord() {
		return previousWord;
	}

        public void setActiveKey(boolean b)
        {
           activeKey=b;
        }
	// Tạo từ khóa
	public void setKeyWord(boolean b) {
		if (b == true) {
			activeKey = true;
			doSelectStart = true;
		} else {
			setKeyWord = false;
			keyWord = null;
		}
		repopulateWords();
	}

	// Lấy biến ghi sự xuất hiện của từ khóa
	public boolean getKeyWord() {
		return setKeyWord;
	}

	// Lấy từ khóa
	public Word getKey() {
		return keyWord;
	}

	// Lấy danh sách các Square
	public ArrayList getSquares() {
		return squares;
	}

	// Khởi tạo việc thêm từ bằng đồ họa
	public void setDoSelectStart(boolean b) {
		startSquare = null;
		doSelectStart = b;
	}

	public boolean getDoSelectStart() {
		return doSelectStart;
	}

	public void setDoSelectEnd(boolean b) {
		doSelectEnd = b;
	}

	public boolean getDoSelectEnd() {
		return doSelectEnd;
	}

	/******************************* Tìm Square ********************************/

	// Tìm một Square theo tọa độ
	public Square findSquare(int x, int y) {
		Square s = null;
		for (int i = 0; i < squares.size(); i++) {
			Square s2 = (Square) squares.get(i);
			if (s2.getXPos() == x && s2.getYPos() == y) {
				s = s2;
			}
		}
		return s;
	}

	// Tìm xem một Square có phải là bắt đầu một từ không, và nó bắt đâu với số
	// thứ tự là bao nhiêu
	public int findStartSquare(Square s) {
		for (int i = 0; i < 4; i++) {
			Word word = s.getWord();
			if (word != null) {
				if (s.getXPos() == word.getY() && s.getYPos() == word.getX())
					return s.getWordIndex();
			}

		}
		return -1;
	}

	// Tìm xem một Square có phải là kết thúc một từ không, và nó kết thúc với
	// độ dài là bao nhiêu
	public int findEndSquare(Square s) {
		for (int i = 0; i < 4; i++) {
			Word word = s.getWord();
			if (word != null) {
				if (word.getWordDirection() == Word.ACROSS) {
					if (word.getX() + word.getLength() - 1 == s.getYPos()) {
						return word.getLength();
					}
				}
				if (word.getWordDirection() == Word.DOWN) {
					if (word.getY() + word.getLength() - 1 == s.getXPos()) {
						return word.getLength();
					}
				}
				if (word.getWordDirection() == Word.BIAS1) {
					if (word.getX() + word.getLength() - 1 == s.getYPos()
							&& word.getY() + word.getLength() - 1 == s
									.getXPos()) {
						return word.getLength();
					}
				}
				if (word.getWordDirection() == Word.BIAS2) {
					if (word.getX() + word.getLength() - 1 == s.getYPos()
							&& word.getY() - word.getLength() + 1 == s
									.getXPos()) {
						return word.getLength();
					}
				}
			}
		}
		return -1;
	}

	// Lấy Square kế tiếp của Square đang chọn
	public Square getNextSquare() {
		if (selectedWord != null) {
			if (selectedWord.getWordDirection() == Word.ACROSS) {
				Square s = findSquare(selectedSquare.getXPos(), selectedSquare
						.getYPos() + 1);
				if (s != null
						&& s.getYPos() < selectedWord.getX()
								+ selectedWord.getLength())
					return s;
			} else if (selectedWord.getWordDirection() == Word.DOWN) {
				Square s = findSquare(selectedSquare.getXPos() + 1,
						selectedSquare.getYPos());
				if (s != null
						&& s.getXPos() < selectedWord.getY()
								+ selectedWord.getLength())
					return s;
			} else if (selectedWord.getWordDirection() == Word.BIAS1) {
				Square s = findSquare(selectedSquare.getXPos() + 1,
						selectedSquare.getYPos() + 1);
				if (s != null
						&& s.getXPos() < selectedWord.getY()
								+ selectedWord.getLength())
					return s;
			} else if (selectedWord.getWordDirection() == Word.BIAS2) {
				Square s = findSquare(selectedSquare.getXPos() - 1,
						selectedSquare.getYPos() + 1);
				if (s != null
						&& s.getYPos() < selectedWord.getX()
								+ selectedWord.getLength())
					return s;
			}
		}
		return selectedSquare;
	}

	// Lấy Square phía trước của Square đang chọn
	public Square getPreviousSquare() {
		if (selectedWord != null) {
			if (selectedWord.getWordDirection() == Word.ACROSS) {
				Square s = findSquare(selectedSquare.getXPos(), selectedSquare
						.getYPos() - 1);
				if (s != null && s.getYPos() >= selectedWord.getX())
					return s;
			} else if (selectedWord.getWordDirection() == Word.DOWN) {
				Square s = findSquare(selectedSquare.getXPos() - 1,
						selectedSquare.getYPos());
				if (s != null && s.getXPos() >= selectedWord.getY())
					return s;
			} else if (selectedWord.getWordDirection() == Word.BIAS1) {
				Square s = findSquare(selectedSquare.getXPos() - 1,
						selectedSquare.getYPos() - 1);
				if (s != null && s.getYPos() >= selectedWord.getX())
					return s;
			} else if (selectedWord.getWordDirection() == Word.BIAS2) {
				Square s = findSquare(selectedSquare.getXPos() + 1,
						selectedSquare.getYPos() - 1);
				if (s != null && s.getYPos() >= selectedWord.getX())
					return s;
			}
		}
		return selectedSquare;
	}

	/*********************************** Gợi ý *****************************************/

	// Tạo gợi ý
	public void writeClue() {
		if (setKeyWord == false
				|| keyWord == null
				|| selectedWord.getWordDirection() != keyWord
						.getWordDirection()) // kiểm tra xem từ tạo clue có phải
												// từ khóa không
		{
			String s1 = JOptionPane.showInputDialog("Nhập gợi ý  1:",
					selectedWord.getClue1());
			selectedWord.setClue1(s1);

			String s2 = JOptionPane.showInputDialog("Nhập gợi ý  2:",
					selectedWord.getClue2());
			selectedWord.setClue2(s2);

			String s3 = JOptionPane.showInputDialog("Nhập gợi ý  3:",
					selectedWord.getClue3());
			selectedWord.setClue3(s3);
		}

		else {
			String s1 = JOptionPane.showInputDialog(
					"Nhập gợi ý của từ khóa chính :", selectedWord.getClue1());
			selectedWord.setClue1(s1);
		}
	}

	// Lấy tên chủ đề của ô chữ
	public String getThemeName(Crossword cw) {
		String theme = "\n        Ô chữ thuộc chủ đề : ";
		switch (cw.getTheme()) {
		case 1:
			theme = theme.concat("English");
			break;
		case 2:
			theme = theme.concat("ICT");
			break;
		case 3:
			theme = theme.concat("Lịch sử");
			break;
		case 4:
			theme = theme.concat("Địa lí");
			break;
		case 5:
			theme = theme.concat("Khoa học");
			break;
		case 6:
			theme = theme.concat("Giải trí");
			break;
		default:
			theme = theme.concat("Khác");
			break;
		}
		return theme;
	}

	// Lấy các gợi ý
	public String getKeywordClue() {
		String s1 = null;

		if (selectedWord != null)
			s1 = selectedWord.getClue1();
		return (" \n" +"        Từ khóa gồm : "+ selectedWord.getLength()+" chữ cái\n"+"    * Gợi ý : " + s1 + "\n");
	}

	public String getSelectedClue1() {
		String s1 = null;
		if (selectedWord != null) {
			if (setKeyWord == true && keyWord != null) {
				if (selectedWord.getWordDirection() == keyWord
						.getWordDirection()) {
					return getKeywordClue();
				}
			}
			s1 = selectedWord.getClue1();
		}
		return ("         Từ này có : "+selectedWord.getLength()+" chữ cái\n"+" - " + s1 + "\n");
	}

	public String getSelectedClue2() {
		String s2 = null;
		if (selectedWord != null) {
			if (setKeyWord == true && keyWord != null) {
				if (selectedWord.getWordDirection() == keyWord
						.getWordDirection()) {
					return getKeywordClue();
				}
			}
			s2 = selectedWord.getClue2();
		}
		return (getSelectedClue1() + " - " + s2 + "\n");

	}

	public String getSelectedClue3() {
		String s3 = null;
		if (selectedWord != null) {
			if (setKeyWord == true && keyWord != null) {
				if (selectedWord.getWordDirection() == keyWord
						.getWordDirection()) {
					return getKeywordClue();
				}
			}
			s3 = selectedWord.getClue3();
		}
		return (getSelectedClue2() + " - " + s3);
	}

	// set số lần bật gợi ý của một từ
	public void setClueUsed(int click) {
		if (selectedWord != null) {
			selectedWord.setClueUsed(click);
		}
	}

	public int getClueUsed() {
		return selectedWord.getClueUsed();
	}

	public void setTime(int a, int b) {
		crossword.setMin(a);
		crossword.setSec(b);
	}

	// *************Các phuơng thức kiểm tra************************

	// kiểm tra từ khóa có thỏa mãn yêu cầu không
	public boolean checkKeyWord(Word a) {
		ArrayList al = crossword.getWords();
		for (int i = 0; i < al.size(); i++) {
			Word w = (Word) al.get(i);
			if (checkIntersection(a, w) == false)
				return false;
		}
		return true;
	}

	// kiểm tra xem từ nhập vào có bị trùng không
	public boolean checkWordDuplicate(String s) {
		StringBuffer buffer = new StringBuffer();
		ArrayList al = crossword.getWords();
		int check = 0;
		for (int i = 0; i < al.size(); i++) {
			Word w = (Word) al.get(i);
			ArrayList letter = w.getLetters();
			for (int j = 0; j < letter.size(); j++) {
				buffer.append(letter.get(j));
			}
			if (s.toUpperCase().equals(buffer.toString().toUpperCase())) {
				check = 1;
				positionDuplicate = w.getWordIndex();
				break;
			}
			buffer = buffer.delete(0, buffer.length());
		}
		if (check == 1)
			return true;
		else
			return false;
	}

	// kiểm tra xem hai từ có giao nhau không
	public boolean checkIntersection(Word a, Word b) {
		if (a.getWordDirection() == Word.ACROSS) {
			for (int i = 0; i < a.getLength(); i++) {
				Square s = findSquare(a.getY(), a.getX() + i);
				if (s.getWord(b.getWordDirection()) == b)
					return true;
			}
			return false;
		} else if (a.getWordDirection() == Word.DOWN) {
			for (int i = 0; i < a.getLength(); i++) {
				Square s = findSquare(a.getY() + i, a.getX());
				if (s.getWord(b.getWordDirection()) == b)
					return true;
			}
			return false;
		} else if (a.getWordDirection() == Word.BIAS1) {
			for (int i = 0; i < a.getLength(); i++) {
				Square s = findSquare(a.getY() + i, a.getX() + i);
				if (s.getWord(b.getWordDirection()) == b)
					return true;
			}
			return false;
		} else {
			for (int i = 0; i < a.getLength(); i++) {
				Square s = findSquare(a.getY() - i, a.getX() + i);
				if (s.getWord(b.getWordDirection()) == b)
					return true;
			}
			return false;
		}
	}

	// kiểm tra xem từ đó có đè lên ô chữ của từ khác không
	public boolean checkReplace(Word a) {
		Word temp;
		if (a.getWordDirection() == Word.ACROSS) {
			for (int i = 0; i < a.getLength(); i++) {
				Square s = findSquare(a.getY(), a.getX() + i);
				temp = s.getWord(Word.ACROSS);
				if (temp != null && temp != a)
					return true;
			}
			return false;
		} else if (a.getWordDirection() == Word.DOWN) {
			for (int i = 0; i < a.getLength(); i++) {
				Square s = findSquare(a.getY() + i, a.getX());
				temp = s.getWord(Word.DOWN);
				if (temp != null && temp != a)
					return true;
			}
			return false;
		} else if (a.getWordDirection() == Word.BIAS1) {
			for (int i = 0; i < a.getLength(); i++) {
				Square s = findSquare(a.getY() + i, a.getX() + i);
				temp = s.getWord(Word.BIAS1);
				if (temp != null && temp != a)
					return true;
			}
			return false;
		} else {
			for (int i = 0; i < a.getLength(); i++) {
				Square s = findSquare(a.getY() - i, a.getX() + i);
				temp = s.getWord(Word.BIAS2);
				if (temp != null && temp != a)
					return true;
			}
			return false;
		}
	}

	/*************************************** Thiết lập chữ cái ************************/

	// Thiết lập chữ cái ở một ô

	public void setLetter(Square s, String temp) {
		Word w = null;
		int letterIndex;
		w = s.getWordAcross();
		if (w != null) {
			letterIndex = s.getYPos() - w.getX();
			w.addLetter(temp, letterIndex);
		}
		w = s.getWordDown();
		if (w != null) {
			letterIndex = s.getXPos() - w.getY();
			w.addLetter(temp, letterIndex);
		}
		w = s.getWordBias1();
		if (w != null) {
			letterIndex = s.getXPos() - w.getY();
			w.addLetter(temp, letterIndex);
		}
		w = s.getWordBias2();
		if (w != null) {
			letterIndex = s.getYPos() - w.getX();
			w.addLetter(temp, letterIndex);
		}
	}

	// Thiết lập chữ cái của một từ khi có tranh chấp
	public void setLetter(Word w) {
		if (w.getWordDirection() == Word.ACROSS) {
			ArrayList<Integer> index = new ArrayList<Integer>();
			ArrayList<String> str = new ArrayList<String>();
			for (int i = w.getX(), letterIndex = 0; i <= w.getX()
					+ w.getLength() - 1; i++, letterIndex++) {
				Square s = findSquare(w.getY(), i);
				if (s.getWordDown() != null) {
					Word temp = s.getWordDown();
					String st1 = (String) w.getLetters().get(letterIndex);
					st1 = st1.toUpperCase();
					int int1 = s.getXPos() - temp.getY();
					String st2 = (String) temp.getLetters().get(int1);
					st2 = st2.toUpperCase();
					if (st1.equals(" ") || st1.equals("") || st1.equals("*")) {
						setLetter(s, st2);
					} else if (st2.equals(" ") || st2.equals("")
							|| st2.equals("*")) {
						setLetter(s, st1);
					} else if (st1.equals(st2) != true) {
						index.add(letterIndex);
						str.add(st2);
					}
				} else if (s.getWordBias1() != null) {
					Word temp = s.getWordBias1();
					String st1 = (String) w.getLetters().get(letterIndex);
					st1 = st1.toUpperCase();
					int int1 = s.getXPos() - temp.getY();
					String st2 = (String) temp.getLetters().get(int1);
					st2 = st2.toUpperCase();
					if (st1.equals(" ") || st1.equals("") || st1.equals("*")) {
						setLetter(s, st2);
					} else if (st2.equals(" ") || st2.equals("")
							|| st2.equals("*")) {
						setLetter(s, st1);
					} else if (st1.equals(st2) != true) {
						index.add(letterIndex);
						str.add(st2);
					}
				} else if (s.getWordBias2() != null) {
					Word temp = s.getWordBias2();
					String st1 = (String) w.getLetters().get(letterIndex);
					st1 = st1.toUpperCase();
					int int1 = s.getYPos() - temp.getX();
					String st2 = (String) temp.getLetters().get(int1);
					st2 = st2.toUpperCase();
					if (st1.equals(" ") || st1.equals("") || st1.equals("*")) {
						setLetter(s, st2);
					} else if (st2.equals(" ") || st2.equals("")
							|| st2.equals("*")) {
						setLetter(s, st1);
					} else if (st1.equals(st2) != true) {
						index.add(letterIndex);
						str.add(st2);
					}
				}

			}
			if (index.isEmpty()) {

			} else {
				int k = JOptionPane.showConfirmDialog(null, "Ghi đè chữ?",
						"Confirm Action", JOptionPane.YES_NO_OPTION);
				if (k == JOptionPane.YES_OPTION) {
					for (int i = 0; i < index.size(); i++) {
						int letterIndex = index.get(i);
						Square s = findSquare(w.getY(), w.getX() + letterIndex);
						setLetter(s, (String) w.getLetters().get(letterIndex));
					}
				} else {
					for (int i = 0; i < index.size(); i++) {
						int letterIndex = index.get(i);
						Square s = findSquare(w.getY(), w.getX() + letterIndex);
						setLetter(s, str.get(i));
					}
				}

			}

		} else if (w.getWordDirection() == Word.DOWN) {
			ArrayList<Integer> index = new ArrayList<Integer>();
			ArrayList<String> str = new ArrayList<String>();
			for (int i = w.getY(), letterIndex = 0; i <= w.getY()
					+ w.getLength() - 1; i++, letterIndex++) {
				Square s = findSquare(i, w.getX());
				if (s.getWordAcross() != null) {
					Word temp = s.getWordAcross();
					String st1 = (String) w.getLetters().get(letterIndex);
					st1 = st1.toUpperCase();
					int int1 = s.getYPos() - temp.getX();
					String st2 = (String) temp.getLetters().get(int1);
					st2 = st2.toUpperCase();
					if (st1.equals(" ") || st1.equals("") || st1.equals("*")) {
						setLetter(s, st2);
					} else if (st2.equals(" ") || st2.equals("")
							|| st2.equals("*")) {
						setLetter(s, st1);
					} else if (st1.equals(st2) != true) {
						index.add(letterIndex);
						str.add(st2);
					}
				} else if (s.getWordBias1() != null) {
					Word temp = s.getWordBias1();
					String st1 = (String) w.getLetters().get(letterIndex);
					st1 = st1.toUpperCase();
					int int1 = s.getXPos() - temp.getY();
					String st2 = (String) temp.getLetters().get(int1);
					st2 = st2.toUpperCase();
					if (st1.equals(" ") || st1.equals("") || st1.equals("*")) {
						setLetter(s, st2);
					} else if (st2.equals(" ") || st2.equals("")
							|| st2.equals("*")) {
						setLetter(s, st1);
					} else if (st1.equals(st2) != true) {
						index.add(letterIndex);
						str.add(st2);
					}
				} else if (s.getWordBias2() != null) {
					Word temp = s.getWordBias2();
					String st1 = (String) w.getLetters().get(letterIndex);
					st1 = st1.toUpperCase();
					int int1 = s.getYPos() - temp.getX();
					String st2 = (String) temp.getLetters().get(int1);
					st2 = st2.toUpperCase();
					if (st1.equals(" ") || st1.equals("") || st1.equals("*")) {
						setLetter(s, st2);
					} else if (st2.equals(" ") || st2.equals("")
							|| st2.equals("*")) {
						setLetter(s, st1);
					} else if (st1.equals(st2) != true) {
						index.add(letterIndex);
						str.add(st2);
					}
				}
			}
			if (index.isEmpty()) {

			} else {
				int k = JOptionPane.showConfirmDialog(null, "Ghi đè chữ?",
						"Confirm Action", JOptionPane.YES_NO_OPTION);
				if (k == JOptionPane.YES_OPTION) {
					for (int i = 0; i < index.size(); i++) {
						int letterIndex = index.get(i);
						Square s = findSquare(w.getY() + letterIndex, w.getX());
						setLetter(s, (String) w.getLetters().get(letterIndex));
					}
				} else {
					for (int i = 0; i < index.size(); i++) {
						int letterIndex = index.get(i);
						Square s = findSquare(w.getY() + letterIndex, w.getX());
						setLetter(s, str.get(i));
					}
				}
			}
		} else if (w.getWordDirection() == Word.BIAS1) {
			ArrayList<Integer> index = new ArrayList<Integer>();
			ArrayList<String> str = new ArrayList<String>();
			for (int i = w.getY(), letterIndex = 0; i <= w.getY()
					+ w.getLength() - 1; i++, letterIndex++) {
				Square s = findSquare(i, w.getX() + letterIndex);
				if (s.getWordAcross() != null) {
					Word temp = s.getWordAcross();
					String st1 = (String) w.getLetters().get(letterIndex);
					st1 = st1.toUpperCase();
					int int1 = s.getYPos() - temp.getX();
					String st2 = (String) temp.getLetters().get(int1);
					st2 = st2.toUpperCase();
					if (st1.equals(" ") || st1.equals("") || st1.equals("*")) {
						setLetter(s, st2);
					} else if (st2.equals(" ") || st2.equals("")
							|| st2.equals("*")) {
						setLetter(s, st1);
					} else if (st1.equals(st2) != true) {
						index.add(letterIndex);
						str.add(st2);
					}
				} else if (s.getWordDown() != null) {
					Word temp = s.getWordDown();
					String st1 = (String) w.getLetters().get(letterIndex);
					st1 = st1.toUpperCase();
					int int1 = s.getXPos() - temp.getY();
					String st2 = (String) temp.getLetters().get(int1);
					st2 = st2.toUpperCase();
					if (st1.equals(" ") || st1.equals("") || st1.equals("*")) {
						setLetter(s, st2);
					} else if (st2.equals(" ") || st2.equals("")
							|| st2.equals("*")) {
						setLetter(s, st1);
					} else if (st1.equals(st2) != true) {
						index.add(letterIndex);
						str.add(st2);
					}
				} else if (s.getWordBias2() != null) {
					Word temp = s.getWordBias2();
					String st1 = (String) w.getLetters().get(letterIndex);
					st1 = st1.toUpperCase();
					int int1 = s.getYPos() - temp.getX();
					String st2 = (String) temp.getLetters().get(int1);
					st2 = st2.toUpperCase();
					if (st1.equals(" ") || st1.equals("") || st1.equals("*")) {
						setLetter(s, st2);
					} else if (st2.equals(" ") || st2.equals("")
							|| st2.equals("*")) {
						setLetter(s, st1);
					} else if (st1.equals(st2) != true) {
						index.add(letterIndex);
						str.add(st2);
					}
				}

			}
			if (index.isEmpty()) {

			} else {
				int k = JOptionPane.showConfirmDialog(null, "Ghi đè chữ?",
						"Confirm Action", JOptionPane.YES_NO_OPTION);
				if (k == JOptionPane.YES_OPTION) {
					for (int i = 0; i < index.size(); i++) {
						int letterIndex = index.get(i);
						Square s = findSquare(w.getY() + letterIndex, w.getX()
								+ letterIndex);
						setLetter(s, (String) w.getLetters().get(letterIndex));
					}
				} else {
					for (int i = 0; i < index.size(); i++) {
						int letterIndex = index.get(i);
						Square s = findSquare(w.getY() + letterIndex, w.getX()
								+ letterIndex);
						setLetter(s, str.get(i));
					}
				}

			}
		} else if (w.getWordDirection() == Word.BIAS2) {
			ArrayList<Integer> index = new ArrayList<Integer>();
			ArrayList<String> str = new ArrayList<String>();
			for (int i = w.getX(), letterIndex = 0; i <= w.getX()
					+ w.getLength() - 1; i++, letterIndex++) {
				Square s = findSquare(w.getY() - letterIndex, i);
				if (s.getWordAcross() != null) {
					Word temp = s.getWordAcross();
					String st1 = (String) w.getLetters().get(letterIndex);
					st1 = st1.toUpperCase();
					int int1 = s.getYPos() - temp.getX();
					String st2 = (String) temp.getLetters().get(int1);
					st2 = st2.toUpperCase();

					if (st1.equals(" ") || st1.equals("") || st1.equals("*")) {
						setLetter(s, st2);
					} else if (st2.equals(" ") || st2.equals("")
							|| st2.equals("*")) {
						setLetter(s, st1);
					} else if (st1.equals(st2) != true) {
						index.add(letterIndex);
						str.add(st2);
					}
				} else if (s.getWordDown() != null) {
					Word temp = s.getWordDown();
					String st1 = (String) w.getLetters().get(letterIndex);
					st1 = st1.toUpperCase();
					int int1 = s.getXPos() - temp.getY();
					String st2 = (String) temp.getLetters().get(int1);
					st2 = st2.toUpperCase();

					if (st1.equals(" ") || st1.equals("") || st1.equals("*")) {
						setLetter(s, st2);
					} else if (st2.equals(" ") || st2.equals("")
							|| st2.equals("*")) {
						setLetter(s, st1);
					} else if (st1.equals(st2) != true) {
						index.add(letterIndex);
						str.add(st2);
					}
				} else if (s.getWordBias1() != null) {
					Word temp = s.getWordBias1();
					String st1 = (String) w.getLetters().get(letterIndex);
					int int1 = s.getYPos() - temp.getX();
					String st2 = (String) temp.getLetters().get(int1);
					st1 = st1.toUpperCase();
					st2 = st2.toUpperCase();
					if (st1.equals(" ") || st1.equals("") || st1.equals("*")) {
						setLetter(s, st2);
					} else if (st2.equals(" ") || st2.equals("")
							|| st2.equals("*")) {
						setLetter(s, st1);
					} else if (st1.equals(st2) != true) {
						index.add(letterIndex);
						str.add(st2);
					}
				}

			}
			if (index.isEmpty()) {

			} else {
				int k = JOptionPane.showConfirmDialog(null, "Ghi đè chữ?",
						"Confirm Action", JOptionPane.YES_NO_OPTION);
				if (k == JOptionPane.YES_OPTION) {
					for (int i = 0; i < index.size(); i++) {
						int letterIndex = index.get(i);
						Square s = findSquare(w.getY() - letterIndex, w.getX()
								+ letterIndex);
						setLetter(s, (String) w.getLetters().get(letterIndex));
					}
				} else {
					for (int i = 0; i < index.size(); i++) {
						int letterIndex = index.get(i);
						Square s = findSquare(w.getY() - letterIndex, w.getX()
								+ letterIndex);
						setLetter(s, str.get(i));
					}
				}

			}
		}
	}

	/*************************************** Đồ họa ***********************************/

	// Tự động thiết lập số thứ tự của ô chữ
	public void setWordNumbers() {
		int wordNumber = 1;
		boolean incrementNumber = false;

		// Reset lại toàn bộ thứ tự
		ArrayList words = crossword.getWords();
		for (int i = 0; i < words.size(); i++) {
			Word wd = (Word) words.get(i);
			wd.setWordIndex(0);
		}

		for (int i = 0; i < squares.size(); i++) {
			Square s = (Square) squares.get(i);
			if (!s.getIsBlank()) {
				ArrayList al = s.getAllWords();
				for (int j = 0; j < al.size(); j++) {
					Word w = (Word) al.get(j);

					if (w.getWordIndex() == 0) {

						if (keyWord == null) {
							w.setWordIndex(wordNumber);
							incrementNumber = true;
						} else {
							if (w.getWordDirection() != keyWord
									.getWordDirection())// không đánh số thứ tự
														// từ khóa
							{
								w.setWordIndex(wordNumber);
								incrementNumber = true;
							}
						}
					}
				}
				if (incrementNumber)
					wordNumber++;
				incrementNumber = false;
			}
		}
	}

	// Tạo các ô chữ của một từ theo một màu
	public void paint(Color c, Word w) {
		if (w.getWordDirection() == Word.ACROSS) {
			for (int i = 0; i < selectedWord.getLength(); i++) {
				Square s = findSquare(selectedWord.getY(), selectedWord.getX()
						+ i);
				if(w==keyWord||s.getWord(keyWord.getWordDirection())==null) s.setBackground(c);
			}
		} else if (w.getWordDirection() == Word.DOWN) {
			for (int i = 0; i < selectedWord.getLength(); i++) {
				Square s = findSquare(selectedWord.getY() + i, selectedWord
						.getX());
                                if(w==keyWord||s.getWord(keyWord.getWordDirection())==null) s.setBackground(c);
			}
		}
		if (w.getWordDirection() == Word.BIAS1) {
			for (int i = 0; i < selectedWord.getLength(); i++) {
				Square s = findSquare(selectedWord.getY() + i, selectedWord
						.getX()
						+ i);
				if(w==keyWord||s.getWord(keyWord.getWordDirection())==null) s.setBackground(c);
			}
		}
		if (selectedWord.getWordDirection() == Word.BIAS2) {
			for (int i = 0; i < selectedWord.getLength(); i++) {
				Square s = findSquare(selectedWord.getY() - i, selectedWord
						.getX()
						+ i);
				if(w==keyWord||s.getWord(keyWord.getWordDirection())==null) s.setBackground(c);
			}
		}
		validate();
	}

	// Phục hồi các từ
	public void repopulateWords() {

		blankSquares();

		// repopulate words
		ArrayList al = crossword.getWords();
		for (int i = 0; i < al.size(); i++) {
			Word w = (Word) al.get(i);
			ArrayList letters = w.getLetters();

			// Phục hồi chữ cái, tô màu và đánh lại số
			if (w.getWordDirection() == Word.ACROSS) {
				for (int j = 0; j < letters.size(); j++) {
					Square s = findSquare(w.getY(), w.getX() + j);
					if (s.getLetter().equals(" ") || s.getLetter().equals("*")
							|| s.getLetter().equals("")) {
						String let = (String) letters.get(j);
						if (let.equals("*")) {
							let = " ";
						}
						s.setLetter(let);
					}
					if (w != keyWord) {
						s.setBackground(Color.WHITE);
					} else {
						s.setBackground(Color.YELLOW);
					}
					s.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
					if (s.isAnyWordSelected()) {
						if (w != keyWord) {
							s.setBackground(Color.PINK);
							s.setResetColour(Color.PINK);
						} else {
							s.setBackground(Color.YELLOW);
							s.setResetColour(Color.YELLOW);
						}
					}
					if (w != keyWord) {
						if (j == 0) {
							s.setWordIndex(w.getWordIndex());
						}
					}
//					if (j == w.getLength() - 1) {
//						s.setWordLength(w.getLength());
//					}

					if (s == selectedSquare) {
						if (w == keyWord) {
							s.setBackground(Color.YELLOW);
							s.setResetColour(Color.YELLOW);
						} else {
							s.setBackground(Color.RED);
							s.setResetColour(Color.RED);
						}
					}
				}
			} else if (w.getWordDirection() == Word.DOWN) {

				for (int j = 0; j < letters.size(); j++) {
					Square s = findSquare(w.getY() + j, w.getX());
					if (s.getLetter().equals(" ") || s.getLetter().equals("*")
							|| s.getLetter().equals("")) {
						String let = (String) letters.get(j);

						if (let.equals("*")) {
							let = " ";
						}
						s.setLetter(let);
					}
					if (w == keyWord) {
						s.setBackground(Color.YELLOW);
					} else {
						s.setBackground(Color.WHITE);
					}
					s.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
					if (w != keyWord) {
						if (j == 0) {
							s.setWordIndex(w.getWordIndex());

						}
					}
//					if (j == w.getLength() - 1) {
//						s.setWordLength(w.getLength());
//					}

					if (s.isAnyWordSelected()) {
						if (w == keyWord) {
							s.setBackground(Color.YELLOW);
							s.setResetColour(Color.YELLOW);
						} else {
							s.setBackground(Color.PINK);
							s.setResetColour(Color.PINK);
						}
					}
					if (s == selectedSquare) {
						if (w != keyWord) {
							s.setBackground(Color.YELLOW);
							s.setResetColour(Color.YELLOW);
						} else {
							s.setBackground(Color.PINK);
							s.setResetColour(Color.PINK);
						}
					}
				}
			} else if (w.getWordDirection() == Word.BIAS1) {
				for (int j = 0; j < letters.size(); j++) {
					Square s = findSquare(w.getY() + j, w.getX() + j);
					if (s.getLetter().equals(" ") || s.getLetter().equals("*")
							|| s.getLetter().equals("")) {
						String let = (String) letters.get(j);

						if (let.equals("*")) {
							let = " ";
						}
						s.setLetter(let);
					}
					if (w == keyWord) {
						s.setBackground(Color.YELLOW);
					} else {
						s.setBackground(Color.WHITE);
					}
					s.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
					if (w != keyWord) {
						if (j == 0) {
							s.setWordIndex(w.getWordIndex());

						}
					}
//					if (j == w.getLength() - 1) {
//						s.setWordLength(w.getLength());
//					}

					if (s.isAnyWordSelected()) {
						if (w == keyWord) {
							s.setBackground(Color.YELLOW);
							s.setResetColour(Color.YELLOW);
						} else {
							s.setBackground(Color.PINK);
							s.setResetColour(Color.PINK);
						}
					}
					if (s == selectedSquare) {
						if (w != keyWord) {
							s.setBackground(Color.YELLOW);
							s.setResetColour(Color.YELLOW);
						} else {
							s.setBackground(Color.PINK);
							s.setResetColour(Color.PINK);
						}
					}
				}
			} else if (w.getWordDirection() == Word.BIAS2) {
				for (int j = 0; j < letters.size(); j++) {
					Square s = findSquare(w.getY() - j, w.getX() + j);
					if (s.getLetter().equals(" ") || s.getLetter().equals("*")
							|| s.getLetter().equals("")) {
						String let = (String) letters.get(j);

						if (let.equals("*")) {
							let = " ";
						}
						s.setLetter(let);
					}
					if (w == keyWord) {
						s.setBackground(Color.YELLOW);
					} else {
						s.setBackground(Color.WHITE);
					}
					s.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
					if (w != keyWord) {
						if (j == 0) {
							s.setWordIndex(w.getWordIndex());

						}
					}
//					if (j == w.getLength() - 1) {
//						s.setWordLength(w.getLength());
//					}

					if (s.isAnyWordSelected()) {
						if (w == keyWord) {
							s.setBackground(Color.YELLOW);
							s.setResetColour(Color.YELLOW);
						} else {
							s.setBackground(Color.PINK);
							s.setResetColour(Color.PINK);
						}
					}
					if (s == selectedSquare) {
						if (w != keyWord) {
							s.setBackground(Color.YELLOW);
							s.setResetColour(Color.YELLOW);
						} else {
							s.setBackground(Color.PINK);
							s.setResetColour(Color.PINK);
						}
					}
				}
			}
		}
		dissociateSquares();
		validate();
	}

	// Xác định lại các ô có từ đi qua, ghi đè phương thức validate của
	// Container
	@Override
	public void validate() {

		Word temp = null;
		for (int i = 0; i < squares.size(); i++) {
			Square s = (Square) squares.get(i);
			if (s.getWord() != null) {
				if (keyWord != null) {
					temp = s.getWord(keyWord.getWordDirection());
				}
				if (temp == keyWord && temp != null) {
					if (doSelectEnd && s.getBackground() == Color.GREEN) {
						s.setBackground(Color.GREEN);
					}

					else {
						if (s.getResetColour() == Color.MAGENTA
								|| s.getResetColour() == Color.DARK_GRAY) {
							s.setBackground(s.getResetColour());
						}
						if (s.getBackground() == Color.MAGENTA
								|| s.getBackground() == Color.DARK_GRAY) {

						} else {
							s.setBackground(Color.YELLOW);
							if (temp == selectedWord)
								s.setBackground(Color.ORANGE);
						}
					}
				} else {
					if (doSelectEnd && s.getBackground() == Color.GREEN) {
						s.setBackground(Color.GREEN);
					} else {
						if (s.getResetColour() == Color.gray
								|| s.getResetColour() == Color.CYAN) {
							s.setBackground(s.getResetColour());
						}
						if (s.getBackground() == Color.gray
								|| s.getBackground() == Color.CYAN) {

						} else {
							s.setBackground(Color.WHITE);
							if (selectedWord != null) {
								if (s.getWordDown() == selectedWord
										|| s.getWordAcross() == selectedWord
										|| s.getWordBias1() == selectedWord
										|| s.getWordBias2() == selectedWord) {
									s.setBackground(Color.PINK);
								}

							}
						}
					}
				}
				if (s == selectedSquare) {
					if (s.getBackground() == Color.gray
							|| s.getBackground() == Color.CYAN
							|| s.getBackground() == Color.MAGENTA
							|| s.getBackground() == Color.DARK_GRAY) {
						s.setResetColour(s.getBackground());
					}
					s.setBackground(Color.RED);
				}
			}
		}
		super.validate();
	}

	/******************************** Xử lý sự kiện ******************************/

	// Xóa các sự kiện(dùng khi giải ô chữ)
	public void removeListeners() {
		for (int i = 0; i < squares.size(); i++) {
			Square s = (Square) squares.get(i);
			SquareListener ml = (SquareListener) s.getMouseListeners()[0];
			SquareMotionListener mml = (SquareMotionListener) s
					.getMouseMotionListeners()[0];
			s.removeMouseListener(ml);
			s.removeMouseMotionListener(mml);
		}
	}

	// Xử lý các sự kiện của chuột
	class SquareListener implements MouseListener {

		public void mouseClicked(MouseEvent e) // thực hiện khi click chuột
		{
			requestFocus();
			if (doMoveStart == true) // kiểm tra việc kết thúc việc kéo thả
			{
				//ArrayList letter = selectedWord.getLetters();
				if (checkReplace(selectedWord) == true) {
					JOptionPane.showMessageDialog(null,
							"Ô chữ thả không hợp lệ");
					if (keyWord == selectedWord) {
						keyWord = createPreviousWord(previousWord);
					} else {
						createPreviousWord(previousWord);
					}
					deleteSelectedWord();
					selectedWord = previousWord;
					selectedSquare.setResetColour(Color.black);
					selectedSquare = previousSquare;
				} else
					setLetter(selectedWord);
				repopulateWords();
				setWordNumbers();
				doMoveStart = false;
			} else // bắt Square khi click chuột
			{
				if (selectedSquare != null) {
					if (selectedWord != null) {
						selectedWord.setIsSelected(false);
					}
				}
				Square sq = (Square) e.getSource();
				selectedSquare = sq;
				if (option != -1) // kiểm tra xem chức năng thêm từ bằng gõ được
									// khởi tạo không
				{
					startSquare = sq;
					startSquare.setBackground(Color.black);
					startSquare.setResetColour(Color.black);

					if (option == 0) {
						endSquare = findSquare(startSquare.getXPos(),
								startSquare.getYPos() + inputText.length() - 1);
					} else if (option == 1) {
						endSquare = findSquare(startSquare.getXPos()
								+ inputText.length() - 1, startSquare.getYPos());
					} else if (option == 2) {
						endSquare = findSquare(startSquare.getXPos()
								+ inputText.length() - 1, startSquare.getYPos()
								+ inputText.length() - 1);
					} else if (option == 3) {
						endSquare = findSquare(startSquare.getXPos()
								- inputText.length() + 1, startSquare.getYPos()
								+ inputText.length() - 1);
					}
					if (endSquare == null) {
						JOptionPane.showMessageDialog(null,
								"Vị trí này không thể nhập được");
					} else {
						createWordType();
						option = -1;
						repopulateWords();
						setWordNumbers();
					}
				}

				if (doSelectStart) // kiểm tra xem chức năng thêm từ bằng vẽ
									// được khởi tạo không
				{
					sq.setBackground(Color.WHITE);
					sq.setIsBlank(false);
					startSquare = sq;
					startSquare.setBackground(Color.BLUE);
					startSquare.setResetColour(Color.BLUE);
					doSelectStart = false;
					doSelectEnd = true;
				} else if (doSelectEnd) {

					int temp = 0;
					if (sq.getYPos() == startSquare.getYPos()
							&& sq.getXPos() >= startSquare.getXPos()) {
						temp = 1;
					} else if (sq.getXPos() == startSquare.getXPos()
							&& sq.getYPos() >= startSquare.getYPos()) {
						temp = 1;
					} else if (sq.getXPos() - startSquare.getXPos() == sq
							.getYPos()
							- startSquare.getYPos()
							&& sq.getXPos() > startSquare.getXPos()) {
						temp = 1;
					} else if (sq.getXPos() - startSquare.getXPos() == startSquare
							.getYPos()
							- sq.getYPos()
							&& sq.getYPos() > startSquare.getYPos()) {
						temp = 1;
					} else
						temp = 0;
					if (temp == 1) {
						sq.setBackground(Color.WHITE);
						sq.setIsBlank(false);
						endSquare = sq;
						endSquare.setWordIndex(endSquare.getYPos()
								- startSquare.getYPos());
						startSquare.setBackground(Color.WHITE);
						startSquare.setResetColour(Color.WHITE);
						doSelectEnd = false;
						createWordDraw();
						selectedWord = selectedSquare.getWord();
						if (selectedWord != null)
							selectedWord.setIsSelected(true);
						previousWord = selectedWord;
						previousSquare = selectedSquare;
						doSelectEnd = false;
						repopulateWords();
						setWordNumbers();

					} else {
						startSquare.setBackground(Color.BLUE);
						startSquare.setResetColour(Color.BLUE);
					}

				}
				// nếu các chức năng trên không được khởi tạo thì lựa chọn
				// Square vừa click làm selectedSquare
				else {
					selectedWord = selectedSquare.getWord();
					if (selectedWord != null)
						selectedWord.setIsSelected(true);
					previousWord = selectedWord;
					previousSquare = selectedSquare;
					repopulateWords();
				}
			}
		}

		// xử lý sự kiện khi con trỏ chuột vào square nào đó
		public void mouseEntered(MouseEvent e) {
			Square sq = (Square) e.getSource();

			if (doSelectStart) // kiểm tra chức năng tạo từ bằng vẽ có khởi tạo
								// không
			{
				sq.setResetColour(sq.getBackground());
				sq.setBackground(Color.green);
			} else if (doSelectEnd) {
				sq.setResetColour(sq.getBackground());
				sq.setBackground(Color.green);
				endSquare = sq;

				// kiểm tra hướng vẽ để tô màu
				if (sq.getXPos() == startSquare.getXPos()
						& startSquare.getYPos() <= sq.getYPos()) {
					for (int i = 0; i < squares.size(); i++) {
						Square temp = (Square) squares.get(i);
						if (temp.getXPos() == startSquare.getXPos()
								&& temp.getYPos() > startSquare.getYPos()
								&& temp.getYPos() <= sq.getYPos()) {
							temp.setBackground(Color.GREEN);
							temp.setWordLength(-1);

						} else if (temp == startSquare)
							;
						else {
							if (temp.getWord() == null) {
								temp.setBackground(Color.black);
								temp.setWordLength(-1);
							} else {
								if (temp.getBackground() == Color.GREEN)
									temp.setBackground(Color.black);
								if (findStartSquare(temp) != -1) {
									temp.setWordIndex(findStartSquare(temp));
								} else if (findEndSquare(temp) != -1) {
									temp.setWordLength(findEndSquare(temp));
								} else
									temp.setWordLength(-1);
							}
						}
					}
					sq.setWordLength(sq.getYPos() - startSquare.getYPos() + 1);
				} else if (sq.getYPos() == startSquare.getYPos()
						& startSquare.getXPos() < sq.getXPos()) {

					for (int i = 0; i < squares.size(); i++) {
						Square temp = (Square) squares.get(i);
						if (temp.getYPos() == startSquare.getYPos()
								&& temp.getXPos() <= sq.getXPos()
								&& temp.getXPos() > startSquare.getXPos()) {

							temp.setBackground(Color.GREEN);
							temp.setWordLength(-1);
						} else if (temp == startSquare)
							;
						else {
							if (temp.getWord() == null) {
								temp.setBackground(Color.black);
								temp.setWordLength(-1);
							} else {
								if (temp.getBackground() == Color.GREEN)
									temp.setBackground(Color.black);
								if (findStartSquare(temp) != -1) {
									temp.setWordIndex(findStartSquare(temp));
								} else if (findEndSquare(temp) != -1) {
									temp.setWordLength(findEndSquare(temp));
								} else
									temp.setWordLength(-1);
							}
						}
						sq.setWordLength(sq.getXPos() - startSquare.getXPos()
								+ 1);
					}
				} else if (sq.getYPos() - startSquare.getYPos() == sq.getXPos()
						- startSquare.getXPos()
						& startSquare.getXPos() < sq.getXPos()) {

					for (int i = 0; i < squares.size(); i++) {
						Square temp = (Square) squares.get(i);
						if (temp.getYPos() - startSquare.getYPos() == temp
								.getXPos()
								- startSquare.getXPos()
								&& temp.getXPos() <= sq.getXPos()
								&& temp.getXPos() > startSquare.getXPos()) {

							temp.setBackground(Color.GREEN);
							temp.setWordLength(-1);
						} else if (temp == startSquare)
							;
						else {

							if (temp.getWord() == null) {

								temp.setBackground(Color.black);
								temp.setWordLength(-1);
							} else {
								if (temp.getBackground() == Color.GREEN)
									temp.setBackground(Color.black);
								if (findStartSquare(temp) != -1) {
									temp.setWordIndex(findStartSquare(temp));
								} else if (findEndSquare(temp) != -1) {
									temp.setWordLength(findEndSquare(temp));
								} else
									temp.setWordLength(-1);
							}
						}
						sq.setWordLength(sq.getXPos() - startSquare.getXPos()
								+ 1);
					}
				} else if (sq.getYPos() - startSquare.getYPos() == startSquare
						.getXPos()
						- sq.getXPos()
						&& startSquare.getYPos() < sq.getYPos()) {

					for (int i = 0; i < squares.size(); i++) {
						Square temp = (Square) squares.get(i);
						if (temp.getYPos() - startSquare.getYPos() == startSquare
								.getXPos()
								- temp.getXPos()
								&& temp.getYPos() <= sq.getYPos()
								&& temp.getYPos() > startSquare.getYPos()) {

							temp.setBackground(Color.GREEN);
							temp.setWordLength(-1);
						} else if (temp == startSquare)
							;
						else {
							if (temp.getBackground() == Color.GREEN)
								temp.setBackground(Color.black);
							if (temp.getWord() == null) {
								temp.setBackground(Color.black);
								temp.setWordLength(-1);
							} else {
								if (findStartSquare(temp) != -1) {
									temp.setWordIndex(findStartSquare(temp));
								} else if (findEndSquare(temp) != -1) {
									temp.setWordLength(findEndSquare(temp));
								} else
									temp.setWordLength(-1);
							}
						}
						sq.setWordLength(sq.getYPos() - startSquare.getYPos()
								+ 1);
					}
				} else {
					for (int i = 0; i < squares.size(); i++) {
						Square temp = (Square) squares.get(i);
						if (temp != startSquare) {
							if (temp.getWord() == null) {
								temp.setBackground(Color.black);
								temp.setWordLength(-1);
							} else {
								if (temp.getBackground() == Color.GREEN)
									temp.setBackground(Color.black);
								if (findStartSquare(temp) != -1) {
									temp.setWordIndex(findStartSquare(temp));
								} else if (findEndSquare(temp) != -1) {
									temp.setWordLength(findEndSquare(temp));
								} else
									temp.setWordLength(-1);

							}
						}
					}

				}
			} else if (option != -1) // kiểm tra xem chức năng tạo từ bằng gõ có
										// khởi tạo không

			{
				sq.setResetColour(sq.getBackground());
				sq.setBackground(Color.GREEN);
			}
			validate();
		}

		// xử lý sự kiện con trỏ chuột đi khỏi một Square nào đó
		public void mouseExited(MouseEvent e) {
			Square sq = (Square) e.getSource();

			if ((doSelectEnd || doSelectStart) && sq.equals(startSquare))
				sq.setBackground(Color.BLUE);
			else if (sq.getWord() == null)
				sq.setBackground(Color.black);
			if (option != -1) {
				sq.setBackground(sq.getResetColour());
			}
			validate();

		}

		// không sử dụng
		public void mousePressed(MouseEvent e) {
		}

		public void mouseReleased(MouseEvent e) {

		}
	}

	class SquareMotionListener implements MouseMotionListener {
		// xử lý sự kiện con chuột di chuyển
		public void mouseMoved(MouseEvent e) {
			if (doMoveStart == true) // kiểm tra xem sự kiện kéo thả kết thúc

			{
				if (checkReplace(selectedWord) == true) {
					JOptionPane.showMessageDialog(null,
							"Ô chữ thả không hợp lệ");
					if (keyWord == selectedWord) {
						keyWord = createPreviousWord(previousWord);
					} else {
						createPreviousWord(previousWord);
					}
					deleteSelectedWord();
					selectedWord = previousWord;
					selectedSquare.setResetColour(Color.black);
					selectedSquare = previousSquare;
				} else
					setLetter(selectedWord);
				repopulateWords();
				setWordNumbers();
				doMoveStart = false;
			}

		}

		// xử lý sự kiện kéo thả chuột
		public void mouseDragged(MouseEvent e) {
			// chuyển tọa độ chuột sang tọa độ của các Square
			int XPos, YPos, x, y;
			double m, n;
			Square sq = (Square) e.getSource();
			m = 540 / crossword.getWidth();
			n = 510 / crossword.getHeight();

			// tìm từ được dánh dấu để kéo
			if (previousSquare != null) {
				YPos = (int) (previousSquare.getYPos() + e.getX() / m);
				XPos = (int) (previousSquare.getXPos() + e.getY() / n);

				if (XPos < 0 || YPos < 0 || XPos >= crossword.getHeight()
						|| YPos >= crossword.getWidth() || sq != previousSquare) {
				} else {
					nextSquare = findSquare(XPos, YPos);

					if (previousWord == null) {

					} else {
						x = nextSquare.getXPos() - previousSquare.getXPos();
						y = nextSquare.getYPos() - previousSquare.getYPos();
						startSquare = findSquare(previousWord.getY() + x,
								previousWord.getX() + y);
						if (startSquare == null) {
						} else {
							if (previousWord.getWordDirection() == Word.ACROSS) {

								endSquare = findSquare(startSquare.getXPos(),
										startSquare.getYPos()
												+ previousWord.getLength() - 1);
							} else if (previousWord.getWordDirection() == Word.DOWN) {
								endSquare = findSquare(startSquare.getXPos()
										+ previousWord.getLength() - 1,
										startSquare.getYPos());
							} else if (previousWord.getWordDirection() == Word.BIAS1) {
								endSquare = findSquare(startSquare.getXPos()
										+ previousWord.getLength() - 1,
										startSquare.getYPos()
												+ selectedWord.getLength() - 1);
							} else if (previousWord.getWordDirection() == Word.BIAS2) {
								endSquare = findSquare(startSquare.getXPos()
										- previousWord.getLength() + 1,
										startSquare.getYPos()
												+ selectedWord.getLength() - 1);
							}
							if (endSquare == null) {
							}

							// nếu từ lựa chọn hợp lệ thì thêm và xóa theo tọa
							// độ chuột
							else {

								if (selectedWord != keyWord) {
									deleteSelectedWord();
									selectedWord = createWord();
								} else {
									keyWord = null;
									deleteSelectedWord();
									selectedWord = createWord();
									keyWord = selectedWord;
								}

								selectedSquare = nextSquare;
								repopulateWords();
								setWordNumbers();
								doMoveStart = true;

							}

						}
					}
				}
			}
		}

	}

	// xử lý sự kiện bàn phím
	class KListener implements KeyListener {

		// không sử dụng
		public void keyPressed(KeyEvent e) {
		}

		public void keyReleased(KeyEvent e) {
		}

		// sự kiện gõ từ bán phím
		public void keyTyped(KeyEvent e) {
			// requestFocus();
			String s = null;
			Character c = e.getKeyChar();
			if (c == 27) // ESC - Kết thúc việc tạo ô chữ mới
			{
				option = -1;
				doSelectStart = false;
				if (doSelectEnd) {
					doSelectEnd = false;
					startSquare.setBackground(Color.black);
					startSquare.setWordLength(-1);
					endSquare.setWordLength(-1);
					for (int i = 0; i < squares.size(); i++) {
						Square temp = (Square) squares.get(i);
						if (temp.getBackground() == Color.GREEN
								&& temp.getWord() == null)
							temp.setBackground(Color.black);
					}
					validate();
				}
			} else if (c == 8) // backspace - Xóa kí tự trong ô
			{
				s = " ";
			} else if (c == 127) // del - Thực hiện xóa ô
			{
				for (int i = 0; i < 4; i++) {
					Word word = selectedSquare.getWord();
					if (word != null) {
						if (word.getWordDirection() == Word.ACROSS) {
							if (word.getX() + word.getLength() - 1 == selectedSquare
									.getYPos()) {
								selectedSquare.setWordAcross(null);
								word.getLetters().remove(word.getLength() - 1);
								word.setLength(word.getLength() - 1);
								if (word.getLength() == 0) {
									selectedWord = word;
									deleteSelectedWord();
								}

							}
						}

						if (word.getWordDirection() == Word.DOWN) {
							if (word.getY() + word.getLength() - 1 == selectedSquare
									.getXPos()) {
								selectedSquare.setWordDown(null);
								word.getLetters().remove(word.getLength() - 1);
								word.setLength(word.getLength() - 1);
								if (word.getLength() == 0) {
									selectedWord = word;
									deleteSelectedWord();
								}

							}
						}

						if (word.getWordDirection() == Word.BIAS1) {
							if (word.getX() + word.getLength() - 1 == selectedSquare
									.getYPos()
									&& word.getY() + word.getLength() - 1 == selectedSquare
											.getXPos()) {
								selectedSquare.setWordBias1(null);
								word.getLetters().remove(word.getLength() - 1);
								word.setLength(word.getLength() - 1);
								if (word.getLength() == 0) {
									selectedWord = word;
									deleteSelectedWord();
								}

							}
						}

						if (word.getWordDirection() == Word.BIAS2) {
							if (word.getX() + word.getLength() - 1 == selectedSquare
									.getYPos()
									&& word.getY() - word.getLength() + 1 == selectedSquare
											.getXPos()) {
								selectedSquare.setWordBias2(null);
								word.getLetters().remove(word.getLength() - 1);
								word.setLength(word.getLength() - 1);
								if (word.getLength() == 0) {
									selectedWord = word;
									deleteSelectedWord();
								}
							}
						}

					}
				}
				if (selectedSquare.getWord() == null)
					selectedSquare.setResetColour(Color.black);
				repopulateWords();
			} else {
				s = String.valueOf(c);
			}
			// nếu kí tự nhận vào hợp lệ thì thêm vào các từ
			if (s != null) {
				ArrayList al = selectedSquare.getAllWords();
				for (int i = 0; i < al.size(); i++) {
					Word w = (Word) al.get(i);
					if (w.getWordDirection() == Word.ACROSS) {
						w.addLetter(s, selectedSquare.getLetterIndexAcross());
					} else if (w.getWordDirection() == Word.DOWN) {
						w.addLetter(s, selectedSquare.getLetterIndexDown());
					} else if (w.getWordDirection() == Word.BIAS1) {
						w.addLetter(s, selectedSquare.getLetterIndexBias1());
					} else if (w.getWordDirection() == Word.BIAS2) {
						w.addLetter(s, selectedSquare.getLetterIndexBias2());
					}
					if (w.getWord().length() == findEndSquare(selectedSquare)
							&& checkWordDuplicate(w.getWord())
							&& w.getWordIndex() != positionDuplicate) {
						JOptionPane.showMessageDialog(null, w.getWord()
								.toUpperCase()
								+ " trùng với từ đã có", "Word Duplicate",
								JOptionPane.ERROR_MESSAGE);
						for (int j = 0; j < w.getLength(); j++)
							w.addLetter(" ", j);
					}
				}

				selectedSquare.setLetter(s);
				if (!s.equals(" "))
					selectedSquare = getNextSquare();
				else
					selectedSquare = getPreviousSquare();
				validate();
			}
		}
	}
}
